import { TreeMultiMap } from '../project-builder/models/common-model';
import { defaultTaskTag, FilterOption, ProjectTemplateOption, TaskTags } from '../project-builder/models/model-options';

import { ProjectBuildOption, TestCase, TestCaseFun } from './test-case';
import { TestTaskOption } from './test-task-option';

/**
 * 查询或存储测试用例
 */
class TestCaseCollection {
  private readonly testCaseMap: TreeMultiMap<TestCase, TaskTags> =
    new TreeMultiMap<TestCase, TaskTags>(defaultTaskTag);

  /**
   * 查找测试用例
   *
   * @param {Partial<TaskTags> | FilterOption<TaskTags>} tags
   * @return {TestCase[]}
   */
  public findTestCases(tags?: Partial<TaskTags> | FilterOption<TaskTags>): TestCase[] {
    return this.testCaseMap.find(tags);
  }

  /**
   * 添加测试用例
   *
   * @param {TaskTags} taskTags
   * @param {TestCase} testCase
   */
  public add(taskTags: TaskTags, testCase: TestCase) {
    this.testCaseMap.insert(taskTags, testCase);
  }
}

export const testCaseCollection: TestCaseCollection = new TestCaseCollection();

export class TestCaseBuilder {
  private testCase: Partial<TestCase & {
    projectTemplateOption: ProjectTemplateOption
  }>;

  private constructor() {
    this.testCase = {};
  }

  public static builder(): TestCaseBuilder {
    return new TestCaseBuilder();
  }

  /**
   * 设置用例名称
   *
   * @param {string} name
   */
  caseName(name: string) {
    this.testCase.caseName = name;
    return this;
  }

  /**
   * 设置用例描述
   *
   * @param {string} description
   */
  description(description: string) {
    this.testCase.description = description;
    return this;
  }

  /**
   * 设置工程构建参数
   *
   * @param {ProjectBuildOption} builder
   */
  projectBuilderOption(builder: ProjectBuildOption) {
    this.testCase.projectBuilder = builder;
    return this;
  }

  /**
   * 设置工程类型参数
   *
   * @param {ProjectTemplateOption} projectTemplateOption
   */
  projectTemplateOption(projectTemplateOption: ProjectTemplateOption) {
    this.testCase.projectTemplateOption = projectTemplateOption;
    return this;
  }

  /**
   * 设置任务类型参数
   *
   * @param {TestTaskOption} taskConfig
   */
  taskConfig(taskConfig: TestTaskOption) {
    this.testCase.taskConfig = taskConfig;
    return this;
  }

  /**
   * 设置测试函数
   *
   * @param {TestCaseFun} testFun
   */
  testFun(testFun: TestCaseFun) {
    this.testCase.testFun = testFun;
    return this;
  }

  /**
   * 将用例载入到用例集合
   */
  load() {
    if (
      this.testCase.taskConfig === undefined ||
      this.testCase.caseName === undefined ||
      this.testCase.projectBuilder === undefined ||
      this.testCase.testFun === undefined ||
      (this.testCase.projectTemplateOption === undefined
        && !(typeof this.testCase.projectBuilder === 'object' && this.testCase.projectBuilder.template !== undefined))
    ) {
      throw new Error('Necessary parameters are absent from the TestCase!');
    }
    if (this.testCase.projectTemplateOption === undefined) {
      this.testCase.projectTemplateOption = (this.testCase.projectBuilder as any).template;
    }
    testCaseCollection.add({
      caseName: this.testCase.caseName!,
      ...this.testCase.projectTemplateOption!,
      ...this.testCase.taskConfig!
    }, new TestCase(
      this.testCase.caseName!,
      this.testCase.projectBuilder!,
      this.testCase.taskConfig!,
      this.testCase.testFun!,
      this.testCase.description
    ));
  }
}
